#!/usr/bin/perl
# install-module.pl
# Installs a webmin module in a .wbm file

# Check arguments
if (@ARGV > 2 || !@ARGV) {
	die "usage: install-module.pl <module.wbm> [config_directory]";
	}
$file = $ARGV[0];
$config = $ARGV[1] ? $ARGV[1] : "/etc/webmin";
-r $file || die "$file does not exist";
&read_file("$config/config", \%gconfig) ||
	die "$config is not a webmin config directory";
&read_file("$config/miniserv.conf", \%miniserv) ||
	die "Failed to read $config/miniserv.conf";
$root = $miniserv{'root'};
-d $root || die "Webmin directory $root does not exist";

# Check if the module file is valid
open(MOD, $file);
read(MOD, $buf, 2);
close(MOD);
if ($buf eq "\037\235") {
	$pre = "uncompress -c $file";
	}
elsif ($buf eq "\037\213") {
	$pre = "gunzip -c $file";
	}
else {
	$pre = "cat $file";
	}
$tar = `$pre | tar tf - 2>&1`;
die "Failed to untar $file : $tar" if ($?);
foreach $f (split(/\n/, $tar)) {
	if ($f =~ /^\.\/([^\/]+)\/(.*)$/ || $f =~ /^([^\/]+)\/(.*)$/) {
		$mods{$1}++;
		$hasfile{$1,$2}++;
		}
	}
foreach $m (keys %mods) {
	$hasfile{$m,"module.info"} || die "Mising module.info file in $file";
	}
%mods || die "$file contains no modules!";

# Delete existing modules
foreach $m (keys %mods) {
	system("rm -rf $root/$m 2>&1 >/dev/null") if ($m ne 'webmin');
	}

# Extract all the modules and update perl paths
$out = `$pre | (cd $root ; tar xf - 2>&1)`;
die "Failed to extract modules from $file : $out" if ($?);
open(PERL, "$config/perl-path");
chop($perl = <PERL>);
close(PERL);
@st = stat("$root/index.cgi");
foreach $m (keys %mods) {
	system("find $root/$m -name '*.cgi' | $perl $root/perlpath.pl $perl -");
	system("find $root/$m -name '*.pl' | $perl $root/perlpath.pl $perl -");
	system("chown -R $st[4]:$st[5] $root/$m");
	local %minfo;
	&read_file("$root/$m/module.info", \%minfo);
	$desc .= "Installed $minfo{'desc'} in $root/$m\n";
	}

# Copy module config files
$mods = join(' ', keys %mods);
system("$perl $root/copyconfig.pl $gconfig{'os_type'} $gconfig{'os_version'} $root $config $mods");

# Update ACL for the root user, or the first user in the ACL file
open(ACL, "$config/webmin.acl");
chop(@acl = <ACL>);
close(ACL);
foreach $a (@acl) {
	if ($a =~ /^(\S+):/ && ($1 eq 'root' || $1 eq 'admin')) {
		$a .= " $mods";
		$found = 1;
		last;
		}
	}
if (!$found) {
	$acl[0] .= " $mods";
	}
open(ACL, "> $config/webmin.acl");
foreach $a (@acl) {
	print ACL "$a\n";
	}
close(ACL);

# All done!
print $desc;

# read_file(file, &assoc, [&order], [lowercase])
# Fill an associative array with name=value pairs from a file
sub read_file
{
open(ARFILE, $_[0]) || return 0;
while(<ARFILE>) {
	s/\r|\n//g;
        if (!/^#/ && /^([^=]+)=(.*)$/) {
		$_[1]->{$_[3] ? lc($1) : $1} = $2;
		push(@{$_[2]}, $1) if ($_[2]);
        	}
        }
close(ARFILE);
return 1;
}
 
